import React, { Component } from 'react';
import { connect } from 'react-redux';
import echarts from 'echarts';
import { Button, Row, Col, Icon, Badge, Select, Radio, message } from 'antd';
import services from '../../services/api';
import { getCodeByKey } from '../../utils/utils';
import ProgressBox from '../../components/ProgressBox';
import './index.less';
import moment from 'moment';

const Option = Select.Option;

function mapStateToProps(state) {
  return {
    strategy_type: state.code.strategy_type || [],
    strategy_mode: state.code.strategy_mode || [],
  };
}

@connect(mapStateToProps)
class Report extends Component {
  constructor(props) {
    super(props);
    this.state = {
      applications: [],
      events: [],
      filterItems: [],
      riskType: '1',
      riskTrendType: 4,
      riskTrend: [],
      requests: [
        {
          value: 0,
        },
        {
          value: 0,
        },
        {
          value: 0,
        },
        {
          value: 0,
        },
      ],
      app_id: '',
      event_id: '',
      start: moment()
        .startOf('week')
        .format('YYYY-MM-DD'),
      end: '',
      type: '',
      current_start: '',
      rule_id: '',
      ruleTrend: [],
      ruleList: [],
      ruleTop: [],
      policyList: [],
      policy_id: '',
      policyTrend: [],
      strategyType: [],
      strategy_top: [],
      risk_type_top: [],
      risk_event_top: [],
      risk_top_ip: [],
      risk_top_user: [],
      risk_top_device: [],
      riskTopKey: 'risk_top_ip',
      riskTrendChart: 'line',
      minute1Index: 0,
      minute5Index: 0,
      minute30Index: 0,
      endIsToday: true,
      showLeftBtn: false,
      showRightBtn: false,
      endTime: '',
    };
    this.isAppChange = false;
    this.actionType = 'report';
    this.params = {};
    this.trendLine = null;
    this.trendB = null;

    if (props && props.location && props.location.search) {
      this.report_id = getCodeByKey(props.location.search, 'report_id');
      this.send_time = getCodeByKey(props.location.search, 'send_time');
      this.token = getCodeByKey(props.location.search, 'token');
      this.params = {
        report_id: this.report_id,
        send_time: this.send_time,
        token: this.token,
      };
    }
  }

  componentDidMount() {
    this.getQueryParams();
  }

  // 获取时间
  getQueryParams = () => {
    services[this.actionType].getQueryParams(this.params).then((res) => {
      if (res.code === 0) {
        this.setState({
          start: res.data.start,
          end: res.data.end,
        });
        this.getStrategyType();
        this.refreshFilter();
        this.getRuleList();
        this.getRuleTop();
        this.getRiskTrend();
        this.getPolicyList();
      } else {
        message.error(res.msg);
      }
    });
  };

  refreshFilter = () => {
    services[this.actionType].filter(this.params).then((res) => {
      if (res.code === 0) {
        this.setState({
          ...res.data.requests,
        });
        this.drawRiskProportion();
        this.drawRiskEventProportion();
      } else {
        message.error(res.msg);
      }
    });
  };

  getStrategyType = () => {
    services[this.actionType].strategyType(this.params).then((res) => {
      if (res.code === 0) {
        this.setState({
          strategyType: res.data,
        });
      } else {
        message.error(res.msg);
      }
    });
  };

  getPolicyList = () => {
    services[this.actionType].strategyList(this.params).then((res) => {
      if (res.code === 0) {
        this.setState({
          policyList: res.data,
          policy_id: res.data.length > 0 ? res.data[0].strategy_id : '',
        });
        this.getPolicyTrend(this.state.policy_id);
      } else {
        message.error(res.msg);
      }
    });
  };

  getPolicyTrend = (strategy_id) => {
    services[this.actionType]
      .strategyTrend({
        ...this.params,
        strategy_id: strategy_id,
      })
      .then((res) => {
        if (res.code === 0) {
          this.setState({
            policyTrend: res.data,
          });
          this.drawPolicyTrend();
        } else {
          message.error(res.msg);
        }
      });
  };

  prevData = () => {
    switch (this.state.riskTrendType) {
      case 1:
        this.setState(
          {
            minute1Index: this.state.minute1Index + 1,
          },
          this.getRiskTrend
        );
        break;
      case 2:
        this.setState(
          {
            minute5Index: this.state.minute5Index + 1,
          },
          this.getRiskTrend
        );
        break;
      case 3:
        this.setState(
          {
            minute30Index: this.state.minute30Index + 1,
          },
          this.getRiskTrend
        );
        break;
      default:
        break;
    }
  };

  nextData = () => {
    switch (this.state.riskTrendType) {
      case 1:
        this.setState(
          {
            minute1Index: this.state.minute1Index - 1,
          },
          this.getRiskTrend
        );
        break;
      case 2:
        this.setState(
          {
            minute5Index: this.state.minute5Index - 1,
          },
          this.getRiskTrend
        );
        break;
      case 3:
        this.setState(
          {
            minute30Index: this.state.minute30Index - 1,
          },
          this.getRiskTrend
        );
        break;
      default:
        break;
    }
  };

  getStartTime(riskTrendType) {
    let current_start = moment(this.state.start)
      .hour(0)
      .minute(0)
      .second(0)
      .format('YYYY-MM-DD HH:mm:ss');
    const now = new Date();
    if (moment(this.state.end).format('YYYY-MM-DD') === moment(now).format('YYYY-MM-DD')) {
      // 结束日期是当前日
      const endTime = moment(this.state.endTime);
      switch (riskTrendType) {
        case 1:
          current_start = moment(endTime - (this.state.minute1Index + 1) * 3600000).format('YYYY-MM-DD HH:mm:ss');
          break;
        case 2:
          current_start = moment(endTime - (this.state.minute5Index + 1) * 6 * 3600000).format('YYYY-MM-DD HH:mm:ss');
          break;
        case 3:
          current_start = moment(endTime - (this.state.minute30Index + 1) * 24 * 3600000).format('YYYY-MM-DD HH:mm:ss');
          break;
        default:
          break;
      }
    } else {
      // 结束日期不是当前日
      const startTime = moment(this.state.start);
      startTime
        .hour(0)
        .minute(0)
        .second(0);
      switch (this.state.riskTrendType) {
        case 1:
          current_start = moment(startTime - this.state.minute1Index * 3600000).format('YYYY-MM-DD HH:mm:ss');
          break;
        case 2:
          current_start = moment(startTime - this.state.minute5Index * 6 * 3600000).format('YYYY-MM-DD HH:mm:ss');
          break;
        case 3:
          current_start = moment(startTime - this.state.minute30Index * 24 * 3600000).format('YYYY-MM-DD HH:mm:ss');
          break;
        default:
          break;
      }
    }
    return current_start;
  }

  getCurrentTime(riskTrendType) {
    let current_end = moment(this.state.end).format('YYYY-MM-DD HH:mm:ss');
    let current_start = moment(this.state.start).format('YYYY-MM-DD HH:mm:ss');
    const endTime = moment(this.state.end).valueOf();
    switch (riskTrendType) {
      case 1:
        current_end = moment(endTime - this.state.minute1Index * 3600000).format('YYYY-MM-DD HH:mm:ss');
        current_start = moment(endTime - (this.state.minute1Index + 1) * 3600000).format('YYYY-MM-DD HH:mm:ss');
        break;
      case 2:
        current_end = moment(endTime - this.state.minute5Index * 6 * 3600000).format('YYYY-MM-DD HH:mm:ss');
        current_start = moment(endTime - (this.state.minute5Index + 1) * 6 * 3600000).format('YYYY-MM-DD HH:mm:ss');

        break;
      case 3:
        current_end = moment(endTime - this.state.minute30Index * 24 * 3600000).format('YYYY-MM-DD HH:mm:ss');
        current_start = moment(endTime - (this.state.minute30Index + 1) * 24 * 3600000).format('YYYY-MM-DD HH:mm:ss');

        break;
      default:
        break;
    }

    return { current_start, current_end };
  }

  getRiskTrend() {
    let { current_start, current_end } = this.getCurrentTime(this.state.riskTrendType);

    // 计算左右切换按钮的显示隐藏状态，当current_start超出范围时限制在范围内
    let showLeftBtn = false,
      showRightBtn = false;

    if (this.state.riskTrendType !== 4) {
      switch (this.state.riskTrendType) {
        case 1:
          if (this.state.minute1Index !== 0) {
            showRightBtn = true;
          }
          break;
        case 2:
          if (this.state.minute5Index !== 0) {
            showRightBtn = true;
          }
          break;
        case 3:
          if (this.state.minute30Index !== 0) {
            showRightBtn = true;
          }

          break;
        default:
          break;
      }
      if (moment(current_start) >= moment(this.state.start)) {
        showLeftBtn = true;
      } else {
        current_start = this.state.start;
      }
    }
    this.setState({
      showLeftBtn,
      showRightBtn,
    });

    services[this.actionType]
      .riskTrend({
        ...this.params,
        type: this.state.riskTrendType,
        current_start: current_start,
        current_end: current_end,
      })
      .then((res) => {
        if (res.code === 0) {
          this.setState({
            riskTrend: res.data,
          });
          this.drawRiskTrend(this.state.riskTrendChart);
        } else {
          message.error(res.msg);
        }
      });
  }

  getRuleTrend = (rule_id) => {
    services[this.actionType]
      .ruleTrend({
        ...this.params,
        rule_id,
      })
      .then((res) => {
        if (res.code === 0) {
          this.setState({
            ruleTrend: res.data,
          });
          this.drawRuleTrend();
        } else {
          message.error(res.msg);
        }
      });
  };

  getRuleTop = (type) => {
    services[this.actionType]
      .ruleTop({
        ...this.params,
        type: type,
      })
      .then((res) => {
        if (res.code === 0) {
          this.setState({
            ruleTop: res.data,
          });
        } else {
          message.error(res.msg);
        }
      });
  };

  getRuleList = () => {
    services[this.actionType].ruleList(this.params).then((res) => {
      if (res.code === 0) {
        this.setState({
          ruleList: res.data,
          rule_id: res.data.length > 0 ? res.data[0].rule_id : '',
        });
        this.getRuleTrend(this.state.rule_id);
      } else {
        message.error(res.msg);
      }
    });
  };

  drawRiskTrend(type) {
    const data =
      type === 'bar' ? this.state.riskTrend.filter((item) => item.name !== '请求总量') : this.state.riskTrend;
    const series = data.map((item) => {
      return {
        name: item.name,
        type,
        stack: type === 'bar' ? type : item.name,
        data: item.value.map((item) => {
          return item.requests;
        }),
      };
    });
    const option = {
      tooltip: {
        trigger: 'axis',
      },
      legend: {
        data: data.map((item) => {
          return item.name;
        }),
      },
      grid: {
        left: '3%',
        right: '4%',
        bottom: '3%',
        containLabel: true,
      },
      xAxis: {
        type: 'category',
        data:
          data &&
          data[0] &&
          data[0].value.map((item) => {
            return item.index;
          }),
      },
      yAxis: {
        type: 'value',
      },
      series: series,
    };
    if (type === 'line') {
      this.trendB && this.trendB.clear();
      this.trendB = null;
      this.trendLine = echarts.init(this.refs.riskTrend);
      this.trendLine.setOption(option);
    } else if (type === 'bar') {
      this.trendLine && this.trendLine.clear();
      this.trendLine = null;
      this.trendB = echarts.init(this.refs.riskTrend);
      this.trendB.setOption(option);
    }
  }

  drawRiskProportion = () => {
    const total_hit_times = this.state.risk_type_top.reduce((total, it) => {
      return total + it.hit_times;
    }, 0);
    let option = {
      tooltip: {
        trigger: 'item',
        formatter: function(params) {
          return `${params.name}:${params.value}(${Math.floor((params.value / total_hit_times) * 10000) / 100}%)`;
        },
      },
      legend: {
        orient: 'vertical',
        left: 'left',
        data: this.state.risk_type_top.map((item) => {
          return item.risk_type_name;
        }),
      },
      series: [
        {
          name: '访问来源',
          type: 'pie',
          radius: '55%',
          center: ['50%', '60%'],
          data: this.state.risk_type_top.map((item) => {
            return {
              value: item.hit_times,
              name: item.risk_type_name,
            };
          }),
          emphasis: {
            itemStyle: {
              shadowBlur: 10,
              shadowOffsetX: 0,
              shadowColor: 'rgba(0, 0, 0, 0.5)',
            },
          },
        },
      ],
    };
    echarts.init(this.refs.riskProportion).setOption(option);
  };

  drawPolicyTrend = () => {
    let option = {
      tooltip: {
        trigger: 'axis',
      },
      xAxis: {
        type: 'category',
        data: this.state.policyTrend.map((item) => item.index),
      },
      yAxis: {
        type: 'value',
      },
      series: [
        {
          data: this.state.policyTrend.map((item) => item.requests),
          type: 'line',
        },
      ],
    };

    echarts.init(this.refs.policyTrend).setOption(option);
  };

  drawRuleTrend = () => {
    let option = {
      tooltip: {
        trigger: 'axis',
      },
      xAxis: {
        type: 'category',
        data: this.state.ruleTrend.map((item) => item.index),
      },
      yAxis: {
        type: 'value',
      },
      series: [
        {
          data: this.state.ruleTrend.map((item) => item.requests),
          type: 'line',
        },
      ],
    };

    echarts.init(this.refs.ruleTrend).setOption(option);
  };
  drawRiskEventProportion = () => {
    const total_hit_times = this.state.risk_event_top.reduce((total, it) => {
      return total + it.hit_times;
    }, 0);
    let option = {
      tooltip: {
        trigger: 'item',
        formatter: function(params) {
          return `${params.name}:${params.value}(${Math.floor((params.value / total_hit_times) * 10000) / 100}%)`;
        },
      },
      legend: {
        orient: 'vertical',
        left: 'left',
        data: this.state.risk_event_top.map((item) => {
          return item.event_name;
        }),
      },
      series: [
        {
          name: '风险事件占比',
          type: 'pie',
          radius: '55%',
          center: ['50%', '60%'],
          data: this.state.risk_event_top.map((item) => {
            return {
              value: item.hit_times,
              name: item.event_name,
            };
          }),
          emphasis: {
            itemStyle: {
              shadowBlur: 10,
              shadowOffsetX: 0,
              shadowColor: 'rgba(0, 0, 0, 0.5)',
            },
          },
        },
      ],
    };
    echarts.init(this.refs.riskEventProportion).setOption(option);
  };

  disabledDate = (current) => {
    // Can not select days before today and today
    return current && (current > moment().endOf('day') || current < moment().subtract('days', 30));
  };

  render() {
    return (
      <div className='dashboard-page'>
        <Row className='dashboard-row request-statistics' gutter={20}>
          <Col span={6}>
            <div>
              <Icon type='pie-chart' />
              <div>
                <p>{this.state.requests[0].name}</p>
                <p>{this.state.requests[0].value}</p>
              </div>
            </div>
          </Col>
          <Col span={6}>
            <div>
              <Icon type='swap' style={{ color: 'rgb(33, 209, 180)', backgroundColor: 'rgba(33, 209, 180, 0.3)' }} />
              <div>
                <p>
                  {this.state.requests[1].name}
                  <Badge
                    count={
                      (this.state.requests[0].value !== 0
                        ? Math.round((this.state.requests[1].value / this.state.requests[0].value) * 100)
                        : 0) + '%'
                    }
                    style={{ backgroundColor: 'rgb(33, 209, 180)', marginLeft: '10px' }}
                  />
                </p>
                <p>{this.state.requests[1].value}</p>
              </div>
            </div>
          </Col>
          <Col span={6}>
            <div>
              <Icon
                type='exclamation'
                style={{ color: 'rgb(247, 129, 32)', backgroundColor: 'rgba(247, 129, 32, 0.3)' }}
              />
              <div>
                <p>
                  {this.state.requests[2].name}
                  <Badge
                    count={
                      (this.state.requests[0].value !== 0
                        ? Math.round((this.state.requests[2].value / this.state.requests[0].value) * 100)
                        : 0) + '%'
                    }
                    style={{ backgroundColor: 'rgb(247, 129, 32)', marginLeft: '10px' }}
                  />
                </p>
                <p>{this.state.requests[2].value}</p>
              </div>
            </div>
          </Col>
          <Col span={6}>
            <div>
              <Icon
                type='thunderbolt'
                style={{ color: 'rgb(247, 76, 33)', backgroundColor: 'rgba(247, 76, 33, 0.3)' }}
              />
              <div>
                <p>
                  {this.state.requests[3].name}
                  <Badge
                    count={
                      (this.state.requests[0].value !== 0
                        ? Math.round((this.state.requests[3].value / this.state.requests[0].value) * 100)
                        : 0) + '%'
                    }
                    style={{ backgroundColor: 'rgb(247, 76, 33)', marginLeft: '10px' }}
                  />
                </p>
                <p>{this.state.requests[3].value}</p>
              </div>
            </div>
          </Col>
        </Row>
        <Row className='dashboard-row' gutter={20}>
          {/* 第一行 */}
          <Col span={14}>
            <div className='risk-trend-box'>
              <div className='chart-head'>
                <h4>风险趋势统计</h4>
                <div>
                  <Select
                    placeholder='请选择'
                    onChange={(e) => {
                      this.setState(
                        {
                          riskTrendType: e,
                        },
                        this.getRiskTrend
                      );
                    }}
                    value={this.state.riskTrendType}
                    dropdownMatchSelectWidth={false}
                  >
                    <Option value={1} key={1}>
                      每分钟
                    </Option>
                    <Option value={2} key={2}>
                      每5分钟
                    </Option>
                    <Option value={3} key={3}>
                      每30分钟
                    </Option>
                    <Option value={4} key={4}>
                      每天
                    </Option>
                  </Select>
                  <Radio.Group
                    value={this.state.riskType}
                    onChange={(e) => {
                      console.log(e);
                      this.setState({ riskType: e.target.value });
                    }}
                    style={{ marginLeft: '10px' }}
                  >
                    <Radio.Button
                      value='1'
                      onClick={() => {
                        this.drawRiskTrend('line');
                        this.setState({
                          riskTrendChart: 'line',
                        });
                      }}
                    >
                      <Icon type='line-chart' />
                    </Radio.Button>
                    <Radio.Button
                      value='2'
                      onClick={() => {
                        this.drawRiskTrend('bar');
                        this.setState({
                          riskTrendChart: 'bar',
                        });
                      }}
                    >
                      <Icon type='bar-chart' />
                    </Radio.Button>
                  </Radio.Group>
                </div>
              </div>
              <div ref='riskTrend' className='chart-box' />
              {this.state.riskTrendType !== 4 ? (
                <div>
                  {this.state.showLeftBtn ? (
                    <Button onClick={this.prevData} className='prev-btn' shape='circle'>
                      <Icon type='left' />
                    </Button>
                  ) : (
                    ''
                  )}
                  {this.state.showRightBtn ? (
                    <Button onClick={this.nextData} className='next-btn' shape='circle'>
                      <Icon type='right' />
                    </Button>
                  ) : (
                    ''
                  )}
                </div>
              ) : (
                ''
              )}
            </div>
          </Col>
          <Col span={10}>
            <div>
              <div className='chart-head'>
                <h4>风险分类占比</h4>
              </div>
              <div ref='riskProportion' className='chart-box' />
            </div>
          </Col>

          {/* 第二行 */}
          <Col span={14}>
            <div>
              <div className='chart-head'>
                <h4>策略命中趋势</h4>
                <div>
                  <Select
                    placeholder='请选择'
                    allowClear
                    onChange={(e) => {
                      this.getPolicyTrend(e);
                      this.setState({
                        policy_id: e,
                      });
                    }}
                    dropdownMatchSelectWidth={false}
                    value={this.state.policy_id}
                  >
                    {this.state.policyList.map((item) => {
                      return (
                        <Option value={item.strategy_id} key={item.strategy_id}>
                          {item.name}
                          <span style={{ color: '#999' }}>
                            ({item.app_name}-{item.event_name})
                          </span>
                        </Option>
                      );
                    })}
                  </Select>
                </div>
              </div>
              <div ref='policyTrend' className='chart-box' />
            </div>
          </Col>
          <Col span={10}>
            <div>
              <div className='chart-head'>
                <h4>策略命中排行Top10</h4>
              </div>
              {this.state.strategy_top.length > 0 && (
                <ProgressBox
                  leftLabel='策略名称'
                  rightLabel='命中次数'
                  keyValue={['name', 'hit_times']}
                  dataSource={this.state.strategy_top}
                  total={this.state.strategy_top[0].hit_times}
                  renderLabel={(record, index) => {
                    return (
                      <>
                        <span style={{ marginRight: '10px' }}>{index + 1}</span>
                        {record.name}
                        <span style={{ color: '#999' }}>
                          ({record.app_name}-{record.event_name})
                        </span>
                      </>
                    );
                  }}
                />
              )}
            </div>
          </Col>

          {/* 第三行 */}
          <Col span={14}>
            <div>
              <div className='chart-head'>
                <h4>规则命中趋势</h4>
                <div>
                  <Select
                    placeholder='请选择'
                    allowClear
                    onChange={(e) => {
                      this.getRuleTrend(e);
                      this.setState({
                        rule_id: e,
                      });
                    }}
                    value={this.state.rule_id}
                    dropdownMatchSelectWidth={false}
                  >
                    {this.state.ruleList.map((item) => {
                      return (
                        <Option value={item.rule_id} key={item.rule_id}>
                          {item.rule_id}-{item.name}
                        </Option>
                      );
                    })}
                  </Select>
                </div>
              </div>
              <div ref='ruleTrend' className='chart-box' />
            </div>
          </Col>
          <Col span={10}>
            <div>
              <div className='chart-head'>
                <h4>规则命中排行Top10</h4>
                <div>
                  <Select
                    placeholder='请选择策略模式'
                    onChange={(e) => {
                      this.getRuleTop(e);
                      this.setState({
                        type: e,
                      });
                    }}
                    value={this.state.type}
                    allowClear
                    dropdownMatchSelectWidth={false}
                  >
                    {this.state.strategyType &&
                      this.state.strategyType.map((item) => {
                        return (
                          <Option value={item.key} key={item.key}>
                            {item.value}
                          </Option>
                        );
                      })}
                  </Select>
                </div>
              </div>
              {this.state.ruleTop.length > 0 && (
                <ProgressBox
                  leftLabel='规则ID'
                  rightLabel='命中次数'
                  keyValue={['rule_id', 'hit_times']}
                  dataSource={this.state.ruleTop}
                  total={this.state.ruleTop[0].hit_times}
                  renderLabel={(record, index) => {
                    return (
                      <>
                        <span style={{ marginRight: '10px' }}>{index + 1}</span>
                        {record.rule_id}(
                        <span style={{ color: '#999' }}>
                          {record.name}-{record.strategy_mode_name}
                        </span>
                        )
                      </>
                    );
                  }}
                  renderRight={(record) => {
                    return <>{record.hit_times}</>;
                  }}
                />
              )}
            </div>
          </Col>

          {/* 第四行 */}
          <Col span={14}>
            <div>
              <div className='chart-head'>
                <h4>风险事件占比</h4>
              </div>
              <div ref='riskEventProportion' className='chart-box' />
            </div>
          </Col>
          <Col span={10}>
            <div>
              <div className='chart-head'>
                <h4>风险命中排行Top10</h4>
                <div>
                  <Select
                    placeholder='请选择'
                    value={this.state.riskTopKey}
                    onChange={(e) => {
                      this.setState({ riskTopKey: e });
                    }}
                  >
                    <Option value={'risk_top_ip'} key={'risk_top_ip'}>
                      IP
                    </Option>
                    <Option value={'risk_top_user'} key={'risk_top_user'}>
                      账号
                    </Option>
                    <Option value={'risk_top_device'} key={'risk_top_device'}>
                      设备指纹
                    </Option>
                  </Select>
                </div>
              </div>
              {this.state[this.state.riskTopKey].length > 0 && (
                <ProgressBox
                  leftLabel={
                    this.state.riskTopKey === 'risk_top_ip'
                      ? 'IP'
                      : this.state.riskTopKey === 'risk_top_user'
                      ? '账号'
                      : '设备指纹'
                  }
                  rightLabel='命中次数'
                  keyValue={['key', 'request']}
                  dataSource={this.state[this.state.riskTopKey]}
                  total={this.state[this.state.riskTopKey][0].request}
                  renderLabel={(record, index) => {
                    return (
                      <>
                        <span style={{ marginRight: '10px' }}>{index + 1}</span>
                        {record.key}
                      </>
                    );
                  }}
                />
              )}
            </div>
          </Col>
        </Row>
      </div>
    );
  }
}

export default Report;
